var GRAPH;

class Graph{
    cyElement: string;
    layout: string;
    items: Item[];
    edges: Edge[];
    number: number = 0;
    fixedPosition: Item[];
    
    constructor(public lay: string) {
        this.layout = lay;
        this.items = [];
        this.fixedPosition = [];
    }

    isItemInGraph(name: string) {
        return this.items.some(item => item.name === name);
    }
    
    
    createEmptyGraph() {
        this.cyElement = cytoscape({
            container: document.getElementById('graph'),
            style: getStyle(),
            layout: { name: this.layout} 
            });
    }
    
    addElement(str: string, editable: boolean = false) {   
        if(!this.isItemInGraph(str)) {
            var i = new Item('n' + this.number++, str, editable);
            this.items.push(i);
            this.cyElement.add({
                group: 'nodes',
                data: { 
                    id: i.id,
                    name: i.name }
                });
            
            this.rerun();
        }  
        else {
            alert("Graf obsahuje vrchol s rovnakým menom - zmeň názov alebo pridaj názov prázdnemu vrcholu");
        }  
    }
    
    addElements(strings: string[], editable: boolean = false) {
        var nodes = [];
        for (var str of strings) {
            if(!this.isItemInGraph(str)) {
                var i = new Item('n' + this.number++, str, editable);
                this.items.push(i);
                nodes.push({
                group: 'nodes',
                data: {
                    id: i.id,
                    name: i.name
                }
            })}
        }
        this.cyElement.add(nodes);
        this.rerun();
    }

    removeElement(str: string) {
        var element = this.cyElement.$('#' + str);
        this.cyElement.remove(element);
        this.items = this.items.filter(item => item.id != str);
        this.rerun();
    }

    removeElements(strings: string[]) {
        for(var str of strings) {
            var element = this.cyElement.$('#' + str);
            this.cyElement.remove(element);
        }
        this.rerun();
    }

    removeEdgeById(id: string) {
        this.cyElement.remove('edge[target=\'' + id + '\']');
        this.rerun();
    }

    rerun() {
        this.cyElement.layout({name: this.layout}).run();
        for(var item of this.fixedPosition) {
            this.cyElement.$('#' + item.id).position({
                x: item.x,
                y: item.y
              });
        }
    }

    lockElement(str: string) {
        var n = this.getItemByName(str);
        this.cyElement.$('#'+ n.id).ungrabify();
        n.editable = false;
    }

    lockElementMove(str: string) {
        var n = this.getItemByName(str);
        n.locked = true;
        n.editable = false;
    }

    getElement(str: string) {
        return this.cyElement.$('#'+ str);
    }

    getItemByName(str: string) {
        var ar = this.items.filter(i => i.name === str);
        return ar[0];
    }

    connect(str1: string, str2: string) {
        var id1 = this.getIdFromName(str1);
        var id2 = this.getIdFromName(str2);
        if(id1 != null && id2 != null) {
            var edges = [];
            edges.push({
                group: 'edges',
                data: {
                    source: id1,
                    target: id2
            }
        });

        this.cyElement.add(edges);
        this.rerun();
        }
    }

    getIdFromName(str: string) {
        var ar = this.items.filter(i => i.name === str);
        return ar.length > 0 ? ar[0].id : null;
    }

    addOnNodeDiv(node: string) {
        var n = GRAPH.getItemById(node.id());
        if(n.editable) {
                var div = document.getElementById('nodeDiv');
                if(div != null) {
                    document.body.removeChild( div );
                }
               
    
                var makeDiv = function(text){
                    var div = document.createElement('div');
                    var textarea = document.createElement('textarea');
                    var btnOK = document.createElement('BUTTON');
                    div.id = 'nodeDiv';
                    btnOK.id = 'OK';
                    textarea.id = 'text';
                    div.classList.add('popper-div');
                    textarea.innerHTML = text;
                    div.appendChild(textarea);
                    div.appendChild(btnOK);
                    document.body.appendChild( div );
                    return div;
                };
                
                var popperNode = node.popper({
                    content: function(){ return makeDiv(node.data('name'))}
                });
                var updateNode = function(){
                     popperNode.scheduleUpdate();
                };
                node.on('position', updateNode);
                
                $("#OK").click( function() {
                    var text = $('textarea#text').val();
                    if(!GRAPH.isItemInGraph(text)) {
                        var n = GRAPH.cyElement.$id(node.id());
                        var nodeInGraph = GRAPH.getItemById(node.id());
                        nodeInGraph.name = text;
                        n.data('name', text);
                    }
                    else {
                        alert("Graf obsahuje vrchol s rovnakým menom - zmeň názov alebo pridaj názov prázdnemu vrcholu");
                    }
                    var div = document.getElementById('nodeDiv');
                    document.body.removeChild( div );
                    
                });
                //this.cyElement.on('pan zoom resize', updateNode);
            
            }    
    }


    getItemById(str: string) {
        var ar = this.items.filter(i => i.id === str);
        return ar.length > 0 ? ar[0] : null;
    }

    createMenu() {
        this.cyElement.cxtmenu({
            selector: 'node',
            commands: [
                {
                    content: '<span class="fas fa-pencil-alt"></span>',
                    select: function(ele){
                        if(!GRAPH.getItemById(ele.id()).locked) {
                            GRAPH.addOnNodeDiv(ele);
                        }
                        else {
                            alert("Nie je možné upravovať zamknutý vrchol")
                        }
                    }
                },
                {
                    content: '<span class="fas fa-trash-alt"></span>',
                    select: function(ele){
                        if(!GRAPH.getItemById(ele.id()).locked) {
                            GRAPH.removeElement(ele.id());
                        }
                        else {
                            alert("Nie je možné vymazať zamknutý vrchol")
                        }
                    }
                }
            ]
        });
    }

   
}


class Item{
    id: string;
    editable: boolean;
    locked: boolean = false;
    name: string;
    x: number;
    y: number;
    
    constructor(public ID: string, public NAME: string, public edit: boolean = false) {
        this. id = ID;
        this.name = NAME;
        this.editable = edit;
    }

    isEditable() {
        return this.editable;
    }

    setPosition(X: number, Y:number) {
        this.x = X;
        this.y = Y;
    }
}

class Edge {
    items: [Item, Item];

    constructor(public ITEMS: [Item, Item]) {
        this. items = ITEMS;
    }
}

function getStringsFromFile(name: string) {
    
}


function getStyle() {
    return cytoscape.stylesheet()
    .selector('node')
      .css({
        'shape': 'rectangle',
        'width': '70px',
        'height': '50px',
        'background-color': '#38b47b',
        'text-wrap': 'wrap',
        'text-halign': 'center',
        'text-valign': 'center',
        'label': 'data(name)'
      })
    .selector('edge')
      .css({
        'width': 4,
        'line-color': '#ffaaaa'
      });
}

function createGraph(strings: string[], editable: boolean = false, layout: string = "circle") {
    GRAPH = new Graph(layout);
    var newNodes = [];
    for (var s of strings) {
        let item = new Item('n' + GRAPH.number++, s, editable);
        GRAPH.items.push(item);
        newNodes.push({
        data: {
            id: item.id,
            name: item.name
        }
    })}

    GRAPH.cyElement = cytoscape({
        container: document.getElementById('graph'),
        elements: {nodes: newNodes},
        style: getStyle(),
        layout: { name: GRAPH.layout} 
        });

    if(editable) {
        GRAPH.createMenu();
    }


    return GRAPH;
}


function  createEmptyGraph() {
    GRAPH.cyElement = cytoscape({
        container: document.getElementById('graph'),
        style: getStyle(),
        layout: { name: this.layout} 
        });
    return GRAPH;
}


function onButtonClick(div: string, args: string[][]) {

}

